package tool.soft

import akka.stream.Materializer

import java.io.File
import command.CommandExec
import dao._
import models.Tables
import org.joda.time.DateTime
import play.api.mvc.{AnyContent, Request}
import play.twirl.api.Html
import shared.Pojo._
import tool.Pojo._
import tool._
import tool.plot._
import tool.soft.AllSoft.SoftBT

import scala.collection.immutable.SeqMap
import implicits.Implicits._
import models.Tables._
import play.api.data.FormBinding
import tool.softT.DiffAnaSoftBT
import play.api.i18n.Messages
import play.api.libs.ws.WSClient
import utils.Utils
import upickle.default._

/** Created by yz on 15/9/2020
  */
object DiffAnaSoft extends SoftBT with DiffAnaSoftBT {

  override def getResultFileName: String = {
    "Diff_Metabolite.csv"
  }

  override def getResultHtml(missionId: Int)(implicit request: Request[AnyContent], messages: Messages): Html = {
    views.html.user.mission.diffAnaResult(missionId)
  }

  override def produceConfigFile(workspaceDir: File, index: Int)(implicit
      request: Request[AnyContent],
      formBinding: FormBinding
  ) = {
    Utils.t2ConfigFile(workspaceDir, data)
    Utils.t2ConfigFile(data, Tool.getCalculateConfigJsonFile(workspaceDir))
    plot.VolcanoPlot.initConfigFile(workspaceDir, idStr = "")
    plot.ZScore.initConfigFile(workspaceDir, idStr = "")
  }

  def getArg(implicit request: Request[AnyContent], messages: Messages, formBinding: FormBinding): ujson.Value = {
    val methodStr = Tool.getMethod(data.method)
    val fcMethodStr = Tool.getFcMethod(data.fcMethod)
    val isPairedStr = if (data.isPaired) messages("yes") else messages("no")
    val fdrMap = if (data.useFdr) {
      SeqMap(messages("fDRCutoff") -> data.fdr)
    } else {
      SeqMap[String, String]()
    }
    val groupArgMap = if (data.group.isBlank) {
      SeqMap[String, String]()
    } else SeqMap(messages("group") -> data.group)
    val argMap = SeqMap(
      messages("analysisMethod") -> methodStr,
      messages("fCCalculationMethod") -> fcMethodStr,
      messages("pValueCutoff") -> data.pValue,
      messages("log2FCCutoff") -> data.log2FC,
      messages("paired") -> isPairedStr
    ) ++ fdrMap ++ groupArgMap

    writeJs(argMap)
  }

  override def getHtml(missionName: String, missionId: Option[Int])(implicit
      request: Request[AnyContent],
      messages: Messages
  ): Html = {
    views.html.user.soft.diffAna(missionName, missionId)
  }

  override def getMission(implicit
      request: Request[AnyContent],
      matrixFileDataDao: MatrixFileDataDao,
      messages: Messages,
      formBinding: FormBinding
  ): Tables.MissionRow = {
    val input = List(data.file, data.groupFile)
    val argJson = getArg
    MissionRow(
      id = 0,
      missionName = s"${data.missionName}",
      kind = nameStr,
      userId = userId,
      startTime = new DateTime(),
      state = "preparing",
      arg = argJson,
      input = input
    )
  }

  override def produceInputFile(
      workspaceDir: File
  )(implicit request: Request[AnyContent], dao: MyDao, formBinding: FormBinding): Any = {
    val rawDataFile = new File(workspaceDir, "AllMet_Raw.txt")
    Tool.produceRawDataFile(userId, data.file, rawDataFile)

    val originalGroupFile = new File(workspaceDir, "original_group.txt")
    Tool.produceRawGroupFile(userId, data.groupFile, rawDataFile, originalGroupFile)
    val groupFile = Tool.getGroupFile(workspaceDir)
    if (data.group.isBlank) {
      groupFile.fileCopyToDir(workspaceDir)
    } else {
      val groupStr = data.group
      val groups = groupStr.mySplit(" vs ")
      originalGroupFile.txtLines.lineSeqMap
        .filter { map =>
          groups.contains(map("ClassNote"))
        }
        .csvLines
        .toTxtFile(groupFile)
    }
  }

  override def data(implicit request: Request[AnyContent], formBinding: FormBinding) = {
    FormTool.diffAnaForm.bindFromRequest().get
  }

  override def resultDeal(workspaceDir: File, resultDir: File)(implicit ws: WSClient, materializer: Materializer): Unit ={
    super.resultDeal(workspaceDir, resultDir)
    val needConvertFileNamePrefixs = List(
      plot.ZScore.plotO.pngFileNamePrefixIn,
    )
    val convertCommands = Tool.fileConvertCommandsIfExist(workspaceDir, needConvertFileNamePrefixs)
    CommandExec().exec { b =>
      CommandData(workspace = workspaceDir, commands = convertCommands, runFileName = "image_convert.sh")
    }
  }

}
